# -*- coding:utf-8 -*-
# title           :
# description     :
# author          :Python超人
# date            :2023-10-31
# link            :https://gitcode.net/pythoncr/
# python_version  :3.8
# ==============================================================================
import xlwt

from functools import wraps


def cache_result(func):
    cached_results = {}

    @wraps(func)
    def wrapper(*args, **kwargs):
        key = (args, tuple(sorted(kwargs.items())))
        if key in cached_results:
            return cached_results[key]
        result = func(*args, **kwargs)
        cached_results[key] = result
        return result

    return wrapper


class CalendarStyle:

    # @cache_result
    def create_style(self, fore_colour, back_colour, font_bold=False, font_size=10, alignment_vert=1, alignment_horz=2,
                     borders_colour=0, border_styles=(1, 1, 1, 1)):
        """

        @param fore_colour:
        @param back_colour:
        @param font_bold:
        @param font_size:
        @param alignment_vert: 垂直对齐
            0: VERT_TOP
            1: VERT_CENTER
            2: VERT_BOTTOM
            3: VERT_JUSTIFIED
            4: VERT_DISTRIBUTED
        @param alignment_horz: 水平对齐
            0: HORZ_GENERAL
            1: HORZ_LEFT
            2: HORZ_CENTER
            3: HORZ_RIGHT
            4: HORZ_FILLED
            5: HORZ_JUSTIFIED # BIFF4-BIFF8X
            6: HORZ_CENTER_ACROSS_SEL # Centred across selection (BIFF4-BIFF8X)
            7: HORZ_DISTRIBUTED # Distributed (BIFF8X)
        @param borders_colour:
        @param border_styles: 1:细实线 2:小粗实线 3:细虚线 4:中细虚线 5:大粗实线 6:双线 7:细点虚线
                              8:大粗虚线 9:细点划线 10:粗点划线 11:细双点划线 12:粗双点划线 13斜点划线
        @return:

        """
        style = xlwt.XFStyle()
        # 创建一个背景图案对象
        pattern = xlwt.Pattern()
        # 表示是否设置填充，默认 NO_PATTERN(值为0)，不设置任何填充。还有一个选项SOLID_PATTERN(1)，设置填充。
        pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        # 设置填充的前景色赋值为黄色 ，参考：Excel颜色索引对照表
        pattern.pattern_fore_colour = back_colour
        # 设置填充的背景色为蓝色，参考：Excel颜色索引对照表
        pattern.pattern_back_colour = back_colour
        # 把背景图案加到样式里去
        style.pattern = pattern

        # 创建字体
        font = xlwt.Font()
        # 设置字体
        font.name = '微软雅黑'
        # 设置字体颜色为红色，参考：Excel颜色索引对照表
        font.colour_index = fore_colour
        # 字体大小，16为字号，20为衡量单位
        # font.height = 20 * 16
        font.height = 20 * font_size
        font.bold = font_bold
        # 把字体加到样式里去
        style.font = font

        # 创建对齐
        alignment = xlwt.Alignment()
        """
        # 水平对齐
        0: HORZ_GENERAL
        1: HORZ_LEFT
        2: HORZ_CENTER
        3: HORZ_RIGHT
        4: HORZ_FILLED
        5: HORZ_JUSTIFIED # BIFF4-BIFF8X
        6: HORZ_CENTER_ACROSS_SEL # Centred across selection (BIFF4-BIFF8X)
        7: HORZ_DISTRIBUTED # Distributed (BIFF8X)
        """
        alignment.horz = alignment_horz  # 居中
        """
        垂直对齐
        0: VERT_TOP
        1: VERT_CENTER
        2: VERT_BOTTOM
        3: VERT_JUSTIFIED
        4: VERT_DISTRIBUTED
        """
        alignment.vert = alignment_vert
        # 设置自动换行
        alignment.wrap = 1

        # 把对齐加到样式里去
        style.alignment = alignment

        # 创建边框
        borders = xlwt.Borders()

        # 设置上下左右边框为颜色为蓝色
        borders.left_colour = borders_colour
        borders.right_colour = borders_colour
        borders.top_colour = borders_colour
        borders.bottom_colour = borders_colour

        # 设置上下左右边框线型和粗细

        borders.top = border_styles[0]
        borders.right = border_styles[1]
        borders.bottom = border_styles[2]
        borders.left = border_styles[3]

        # 把边框加到样式里去
        style.borders = borders
        return style

    def build_style(self):
        self.default_bg_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color2,
                                                  font_bold=True, font_size=18,
                                                  borders_colour=self.border_color, border_styles=(0, 0, 0, 0))

        self.month_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color2,
                                             font_bold=True, font_size=14,
                                             border_styles=(0, 0, self.border_style, 0),
                                             borders_colour=self.border_color)
        self.year_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color2,
                                            font_bold=True, font_size=24,
                                            borders_colour=self.border_color,
                                            border_styles=(0, 0, 0, 0))

        self.week_style = self.create_style(fore_colour=self.header_font_color, back_colour=self.header_bg_color,
                                            borders_colour=self.border_color, font_bold=True, font_size=12,
                                            border_styles=(
                                                self.border_style, self.border_style, self.header_bottom_border_style,
                                                self.border_style))
        self.week_highlight_style = self.create_style(fore_colour=self.header_highlight_font_color, font_bold=True,
                                                      font_size=12,
                                                      back_colour=self.header_highlight_bg_color,
                                                      borders_colour=self.border_color,
                                                      border_styles=(
                                                          self.border_style, self.border_style,
                                                          self.header_bottom_border_style, self.border_style))

        self.solar_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color, font_bold=True,
                                             font_size=18,
                                             alignment_vert=2,
                                             borders_colour=self.border_color,
                                             border_styles=(self.border_style, self.border_style, 0,
                                                            self.border_style))

        self.solar_highlight_style = self.create_style(fore_colour=self.highlight_font_color,
                                                       back_colour=self.highlight_bg_color,
                                                       font_bold=True,
                                                       font_size=18,
                                                       alignment_vert=2,
                                                       borders_colour=self.border_color,
                                                       border_styles=(
                                                           self.border_style, self.border_style, 0,
                                                           self.border_style))

        self.lunar_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color,
                                             alignment_vert=0,
                                             borders_colour=self.border_color,
                                             border_styles=(0, self.border_style, self.border_style,
                                                            self.border_style))
        self.lunar_highlight_style = self.create_style(fore_colour=self.highlight_font_color,
                                                       alignment_vert=0,
                                                       back_colour=self.highlight_bg_color,
                                                       borders_colour=self.border_color,
                                                       border_styles=(
                                                           0, self.border_style, self.border_style,
                                                           self.border_style))

        self.shared_cell_style = self.create_style(fore_colour=self.font_color, back_colour=self.bg_color,
                                                   borders_colour=self.border_color,
                                                   alignment_horz=1,
                                                   border_styles=(
                                                       0, self.border_style, self.border_style, self.border_style))
        self.shared_cell_style.borders.need_diag2 = 1
        self.shared_cell_style.borders.diag = 1
        self.shared_cell_style.borders.diag_colour = self.border_color

    @cache_result
    def create_font(self, colour_index, font_size, font_bold):
        # 创建字体
        font = xlwt.Font()
        # 设置字体
        font.name = '微软雅黑'
        # 设置字体颜色为红色，参考：Excel颜色索引对照表
        font.colour_index = colour_index
        # 字体大小，16为字号，20为衡量单位
        font.height = 20 * font_size
        font.bold = font_bold
        return font

    @cache_result
    def xf_style(self, styles_str):
        # xlwt.easyxf('font: height 450;')
        return xlwt.easyxf(styles_str)

    @cache_result
    def font_height(self, height):
        return self.xf_style(f'font: height {height};')

    def __init__(self,
                 style_name=None,
                 week_max_rows=5,
                 font_color=0,
                 bg_color=1,
                 bg_color2=None,
                 highlight_font_color=2,
                 highlight_bg_color=None,
                 border_style=1,
                 border_color=0,
                 header_bottom_border_style=1,
                 header_font_color=0,
                 header_bg_color=22,
                 header_highlight_font_color=2,
                 header_highlight_bg_color=None):

        """

        @param style_name: 样式的名称，如果不为空，则为工作表的名称
        @param week_max_rows: 日历上每月周的最大行数，只能为5到6，5行看上去会整齐一些，但是需要共用单元格
        @param font_color: 默认字体颜色
        @param bg_color: 默认背景颜色
        @param bg_color2: 大背景默认颜色
        @param highlight_font_color: 节假日高亮字体颜色
        @param highlight_bg_color: 节假日高亮背景颜色
        @param border_style: 边框样式（0：无边框）
                        1:细实线 2:小粗实线 3:细虚线 4:中细虚线 5:大粗实线 6:双线 7:细点虚线
                        8:大粗虚线 9:细点划线 10:粗点划线 11:细双点划线 12:粗双点划线 13斜点划线
        @param border_color: 边框颜色
        @param header_bottom_border_style: 周标题边框样式
        @param header_font_color: 周标题字体颜色
        @param header_bg_color: 周标题背景颜色
        @param header_highlight_font_color: 周标题节假日高亮字体颜色
        @param header_highlight_bg_color: 周标题节假日高亮背景颜色
        """
        self.style_name = style_name
        if highlight_bg_color is None:
            highlight_bg_color = bg_color
        if header_highlight_bg_color is None:
            header_highlight_bg_color = header_bg_color
        if bg_color2 is None:
            bg_color2 = bg_color
        if week_max_rows not in [5, 6]:
            raise Exception("week_max_rows 只能为 5 或者 6")
        self.week_max_rows = week_max_rows
        self.font_color = font_color
        self.bg_color = bg_color
        self.bg_color2 = bg_color2
        self.highlight_font_color = highlight_font_color
        self.highlight_bg_color = highlight_bg_color
        self.border_style = border_style
        self.border_color = border_color
        self.header_bottom_border_style = header_bottom_border_style
        self.header_font_color = header_font_color
        self.header_bg_color = header_bg_color
        self.header_highlight_font_color = header_highlight_font_color
        self.header_highlight_bg_color = header_highlight_bg_color

        self.default_bg_style = None
        self.month_style = None
        self.year_style = None
        self.week_style = None
        self.week_highlight_style = None
        self.lunar_style = None
        self.lunar_highlight_style = None
        self.solar_style = None
        self.solar_highlight_style = None
        self.shared_cell_style = None

        self.build_style()
